package com.yuzhi.master.sewage.rmstSz.service.Impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.yuzhi.common.core.page.PageDataInfo;
import com.yuzhi.common.util.DateTimeFilterUtils;
import com.yuzhi.common.util.StringUtils;
import com.yuzhi.master.pump.domain.request.BarSeriesItemResult;
import com.yuzhi.master.sewage.rmstSz.entity.request.DrainRmstYwDayResult;
import com.yuzhi.master.sewage.rmstSz.entity.request.DrainRmstYwDayVoReq;
import com.yuzhi.master.sewage.rmstSz.entity.vo.DrainRmstYwDayVo;
import com.yuzhi.master.sewage.rmstSz.mapper.DrainRmstYwDayMapper;
import com.yuzhi.master.sewage.rmstSz.mapper.DrainRmstYwDayVoMapper;
import com.yuzhi.master.sewage.rmstSz.service.DrainRmstSzService;
import com.yuzhi.master.sewage.rmstSz.service.IDrainRmstYwDayService;
import com.yuzhi.master.sewageTreatment.entity.SwageTreatmentEntity;
import com.yuzhi.master.sewageTreatment.mapper.SewageTreatmentMapper;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.time.temporal.TemporalAdjusters;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * 站点液位日数据统计表Service业务层处理
 * @author auto code generator
 * @date 2025-07-04
 */
@RequiredArgsConstructor
@Service
public class DrainRmstYwDayServiceImpl implements IDrainRmstYwDayService {


    private final DrainRmstYwDayMapper drainRmstYwDayMapper;

    private final DrainRmstYwDayVoMapper drainRmstYwDayVoMapper;

    private final DrainRmstSzService drainRmstSzService;

    private final SewageTreatmentMapper sewageTreatmentMapper;


    /**
     * 首页污水处理厂统计
     * @return
     */
    @Override
    public Map<String, Object>  countSewageFactory()
    {
        // 获取今天的开始和结束时间
        LocalDateTime todayStart = LocalDate.now().atStartOfDay();  // 今天 00:00:00
        LocalDateTime todayEnd = LocalDateTime.now();              // 当前时间

        LambdaQueryWrapper<DrainRmstYwDayVo> todayWrapper = new LambdaQueryWrapper<>();
        todayWrapper.between(DrainRmstYwDayVo::getCjTime, todayStart, todayEnd);
        //查询今日数据集合
        List<DrainRmstYwDayVo>  list   =  drainRmstYwDayVoMapper.selectList(todayWrapper);
        // 1、计算今日累计污水处理量(进水量)单位：万立方米/日
        BigDecimal toDayOut  = BigDecimal.ZERO;
        // 今日负荷率
        BigDecimal todayLoadRate = BigDecimal.ZERO;
        if(list!=null && !list.isEmpty())
        {
            //计算今日累计污水处理量(进水量)单位：万立方米/日
            toDayOut  = list.stream()
                    .map(DrainRmstYwDayVo::getCsLg)
                    .filter(Objects::nonNull)
                    .map(BigDecimal::valueOf)
                    .reduce(BigDecimal.ZERO, BigDecimal::add);

            //计算水厂设计规模（万立方米/日）,按 按污水厂ID(factId)去重后求和
            BigDecimal  factCapDsnAll  = list.stream()
                    .collect(Collectors.toMap(
                            DrainRmstYwDayVo::getFactId,  // 以factId作为key
                            vo -> Optional.ofNullable(vo.getFactCapDsn())
                                    .map(BigDecimal::valueOf)
                                    .orElse(BigDecimal.ZERO),  // 处理null值
                            (existing, replacement) -> existing  // 如果factId重复，保留已存在的记录
                    ))
                    .values()  // 获取去重后的值集合
                    .stream()
                    .reduce(BigDecimal.ZERO, BigDecimal::add);

            //计算今日负荷率
            todayLoadRate = toDayOut.divide(factCapDsnAll, 4, RoundingMode.HALF_UP);
        }

        // 获取昨天的开始和结束时间
        LocalDateTime yesterdayStart = LocalDate.now().minusDays(1).atStartOfDay();  // 昨天 00:00:00
        LocalDateTime yesterdayEnd = yesterdayStart.plusDays(1).minusNanos(1);      // 昨天 23:59:59.999999999

        LambdaQueryWrapper<DrainRmstYwDayVo> yesterdayWrapper = new LambdaQueryWrapper<>();
        yesterdayWrapper.between(DrainRmstYwDayVo::getCjTime, yesterdayStart, yesterdayEnd);
        // 获取昨日数据
        List<DrainRmstYwDayVo> yesterdayVos = drainRmstYwDayVoMapper.selectList(yesterdayWrapper);
        //2、计算昨日水力负荷率
        String  yesterdayDataVal  = "0";
        BigDecimal yesterdayLoadRate = BigDecimal.ZERO;
        // 昨日累计污水处理量(进水量)
        BigDecimal  sewageTreatmentOut = BigDecimal.ZERO;
        if(yesterdayVos!=null && !yesterdayVos.isEmpty())
        {
            //昨日累计污水处理量(进水量)
            sewageTreatmentOut  = yesterdayVos.stream()
                    .map(DrainRmstYwDayVo::getCsLg)
                    .filter(Objects::nonNull)
                    .map(BigDecimal::valueOf)
                    .reduce(BigDecimal.ZERO, BigDecimal::add);

            //计算水厂设计规模（万立方米/日）,按 按污水厂ID(factId)去重后求和
            BigDecimal  factCapDsnAll  = yesterdayVos.stream()
                    .collect(Collectors.toMap(
                            DrainRmstYwDayVo::getFactId,  // 以factId作为key
                            vo -> Optional.ofNullable(vo.getFactCapDsn())
                                    .map(BigDecimal::valueOf)
                                    .orElse(BigDecimal.ZERO),  // 处理null值
                            (existing, replacement) -> existing  // 如果factId重复，保留已存在的记录
                    ))
                    .values()  // 获取去重后的值集合
                    .stream()
                    .reduce(BigDecimal.ZERO, BigDecimal::add);
            //计算昨日水力负荷率
            yesterdayLoadRate = sewageTreatmentOut.divide(factCapDsnAll, 4, RoundingMode.HALF_UP);
            yesterdayDataVal  = sewageTreatmentOut.divide(factCapDsnAll, 4, RoundingMode.HALF_UP)
                    .multiply(new BigDecimal("100")).toPlainString() ;
        }

        //3、计算今日污水厂处理量较昨日处理量的百分比
        BigDecimal growthRateCsLg = BigDecimal.ZERO;
        if(sewageTreatmentOut.compareTo(BigDecimal.ZERO) != 0)
        {
            // (今日处理量−昨日处理量)/昨日处理量
            BigDecimal numerator = toDayOut.subtract(sewageTreatmentOut);
            growthRateCsLg  =  numerator.divide(sewageTreatmentOut, 4, RoundingMode.HALF_UP)
                    .multiply(new BigDecimal("100"))  ;
        }

        //4、计算今日污水厂负荷率较昨日负荷率的百分比
        BigDecimal growthRateLoadRate = BigDecimal.ZERO;
        if(yesterdayLoadRate.compareTo(BigDecimal.ZERO) != 0)
        {
            // (今日负荷率−昨日负荷率)/昨日负荷率
            BigDecimal numerator = todayLoadRate.subtract(yesterdayLoadRate);
            growthRateLoadRate  =  numerator.divide(yesterdayLoadRate, 4, RoundingMode.HALF_UP)
                    .multiply(new BigDecimal("100"))  ;
        }

        //对今日水厂处理数据按柱状图展示
        List<SwageTreatmentEntity> factoryList  = sewageTreatmentMapper.selectList();
        // 首先创建一个 factId 到 csLg 总和的映射
        Map<String, Double> factIdToSum = list.stream()
                .filter(vo -> vo.getFactId() != null)  // 过滤掉 factId 为 null 的 DrainRmstYwDayVo
                .collect(Collectors.groupingBy(
                        DrainRmstYwDayVo::getFactId,
                        Collectors.summingDouble(vo -> Optional.ofNullable(vo.getCsLg()).orElse(0.0))
                ));
        // 污水厂当日处理量汇总
        factoryList.forEach(entity -> {
            Double sum = factIdToSum.get(entity.getFactId());
            entity.setCsLg(sum != null ? sum : 0.0); // 污水厂当日处理量汇总
        });

        //按污水厂分类(1：重点污水厂，2、其他厂)过滤出  重点污水厂
        List<SwageTreatmentEntity>  heartVolist = factoryList.stream()
                .filter(user -> user.getDzFact() != null && user.getDzFact() == 1)
                .collect(Collectors.toList());

        //另其他厂家计算合计
        List<SwageTreatmentEntity>  otherVolist = factoryList.stream()
                .filter(user -> user.getDzFact() != null && user.getDzFact() != 1)
                .collect(Collectors.toList());

        //计算其他厂家合计出水量
        BigDecimal  otherSewageTreatmentOut  = otherVolist.stream()
                .map(SwageTreatmentEntity::getCsLg)
                .filter(Objects::nonNull)
                .map(BigDecimal::valueOf)
                .reduce(BigDecimal.ZERO, BigDecimal::add);

        //计算计算其他厂家设计规模（万立方米/日）
        BigDecimal  otherFactCapDsn  = otherVolist.stream()
                .map(SwageTreatmentEntity::getFactCapDsn)
                .filter(Objects::nonNull)
                .reduce(BigDecimal.ZERO, BigDecimal::add);

        //其他厂家
        SwageTreatmentEntity  otherVoInfo  = new SwageTreatmentEntity();
        otherVoInfo.setShortName("其他厂/站");
        otherVoInfo.setCsLg(otherSewageTreatmentOut.doubleValue());
        otherVoInfo.setFactCapDsn(otherFactCapDsn);

        //将其他厂家合计纳入图形列表
        heartVolist.add(otherVoInfo);

        Map<String, Object> chartData = new LinkedHashMap<>();

        //今日累计污水处理量 ,转成“万吨”单位
       String toDayOutStr  = toDayOut.divide(BigDecimal.valueOf(10000), 4, RoundingMode.HALF_UP)
            .stripTrailingZeros()  // 去除末尾多余的零
            .toPlainString();

        chartData.put("toDayOut",toDayOutStr);
        //昨日负荷率
        chartData.put("yesterdayDataVal",yesterdayDataVal);
        // 计算今日污水厂处理量较昨日处理量的百分比
        chartData.put("growthRateCsLg",growthRateCsLg);
        // 计算今日污水厂负荷率较昨日负荷率的百分比
        chartData.put("growthRateLoadRate",growthRateLoadRate);

        // Y轴数据（厂名）
        List<String> storeNames = heartVolist.stream()
                .map(SwageTreatmentEntity::getShortName)
                .collect(Collectors.toList());


        // X轴数据系列
        BarSeriesItemResult csLgInfo =  createSeries("今日出水量", heartVolist, SwageTreatmentEntity::getCsLg);
        BarSeriesItemResult factCapDsn =  createSeries("水厂设计规模", heartVolist, entity -> entity.getFactCapDsn().doubleValue());

        DrainRmstYwDayResult  drainRmstYwDayResult  = new DrainRmstYwDayResult();
        drainRmstYwDayResult.setXSewageFactoryData(storeNames);
        drainRmstYwDayResult.setYSewageFactoryData(Arrays.asList(csLgInfo, factCapDsn));

        chartData.put("drainRmstYwDayResult",drainRmstYwDayResult);

        return chartData;
    }


    private static BarSeriesItemResult createSeries(String name, List<SwageTreatmentEntity> stores,
                                                    Function<SwageTreatmentEntity, Double> valueExtractor) {

        BarSeriesItemResult  barSeriesItemResult  = new BarSeriesItemResult();
        barSeriesItemResult.setSeriesDateName(name);
        barSeriesItemResult.setType("line");

        // 转换为万元单位并确保List<BigDecimal>类型
        List<BigDecimal> dataInTenThousand = stores.stream()
                .map(valueExtractor)
                .map(value -> value != null ? value : 0.0)  // 处理null值
                .map(value -> {
                    BigDecimal decimalValue = BigDecimal.valueOf(value);
                    return decimalValue.divide(BigDecimal.valueOf(10000), 8, RoundingMode.HALF_UP)
                            .setScale(2, RoundingMode.HALF_UP);
                })
                .collect(Collectors.toList());

        barSeriesItemResult.setData(dataInTenThousand);


        return barSeriesItemResult;
    }


    /**
     * 按查询时间类型统计污水厂处理数据
     * @param queryDateType (1:近七日  2:按当前年月  3:按年份)
     * @return
     */
    public Map<String, Object>  countDateSewageFactory(String queryDateType)
    {
        List<DrainRmstYwDayVo>   voList = new ArrayList<>();

        if("1".equals(queryDateType))   //近七日
        {
            LambdaQueryWrapper<DrainRmstYwDayVo> wrapper = new LambdaQueryWrapper<>();
            wrapper.ge(DrainRmstYwDayVo::getCjTime, LocalDateTime.now().minusDays(7))  // 7天前
                    .le(DrainRmstYwDayVo::getCjTime, LocalDateTime.now());            // 到现在
            //查询今日数据集合
            voList   =  drainRmstYwDayVoMapper.selectList(wrapper);
            if(!voList.isEmpty())
            {
                //转换为年-月-日
                DateTimeFormatter formatter = DateTimeFormatter.ofPattern("MM-dd");
                voList.forEach(obj -> {
                    // CjDate(LocalDateTime)转换为String并赋值给CjDateStr
                    obj.setCjTimeStr(obj.getCjTime().format(formatter));
                });
            }
        }
        else if("2".equals(queryDateType))//按月统计
        {
            // 查询当前月份及往前推12个月的时间段
            // 获取当前时间
            LocalDateTime now = LocalDateTime.now();
            //起始时间  算12个月前的起始时间（当月1日 00:00:00）
            LocalDateTime monthStart = now.minusMonths(11)  // 减11个月，因为包含当前月共12个月
                    .withDayOfMonth(1)
                    .withHour(0)
                    .withMinute(0)
                    .withSecond(0);
            // 计算当前月的结束时间（当月最后一天 23:59:59）
            LocalDateTime monthEnd = now.with(TemporalAdjusters.lastDayOfMonth())
                    .withHour(23)
                    .withMinute(59)
                    .withSecond(59);

            LambdaQueryWrapper<DrainRmstYwDayVo> wrapper = new LambdaQueryWrapper<>();
            wrapper.between(DrainRmstYwDayVo::getCjTime, monthStart, monthEnd);

            voList  =  drainRmstYwDayVoMapper.selectList(wrapper);
            if(!voList.isEmpty())
            {
                //转换为年
                DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM");
                voList.forEach(obj -> {
                    // CjDate(LocalDateTime)转换为String并赋值给CjDateStr
                    obj.setCjTimeStr(obj.getCjTime().format(formatter));
                });
            }
        }
        else if("3".equals(queryDateType))//按年统计
        {
            LambdaQueryWrapper<DrainRmstYwDayVo> wrapper = new LambdaQueryWrapper<>();

            //按年份汇总
            voList  =  drainRmstYwDayVoMapper.selectList(wrapper);
            if(!voList.isEmpty())
            {
                //转换为年
                DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy");
                voList.forEach(obj -> {
                    // CjDate(LocalDateTime)转换为String并赋值给CjDateStr
                    obj.setCjTimeStr(obj.getCjTime().format(formatter));
                });
            }
        }

        //按照日期统计数据
        Map<String, double[]> stats = voList.stream()
                .collect(Collectors.groupingBy(
                        DrainRmstYwDayVo::getCjTimeStr,
                        TreeMap::new, // 保持时间顺序
                        Collectors.collectingAndThen(
                                Collectors.toList(),
                                list -> {
                                    // 1. 计算 CsLg（直接求和）
                                    double estimated = list.stream()
                                            .mapToDouble(u -> Optional.ofNullable(u.getCsLg()).orElse(0.0))
                                            .sum();
                                    // 2.计算污水厂设计规模  FactCapDsn（按 factId(污水厂ID)去重后求和）
                                    double actual = list.stream()
                                            .collect(Collectors.toMap(
                                                    DrainRmstYwDayVo::getFactId,
                                                    u -> Optional.ofNullable(u.getFactCapDsn()).orElse(0.0),
                                                    (existing, replacement) -> existing // 去重：保留已存在的值
                                            ))
                                            .values()
                                            .stream()
                                            .mapToDouble(Double::doubleValue)
                                            .sum();
                                    return new double[]{estimated, actual};
                                }
                        )
                ));

        if("4".equals(queryDateType)) //统计当天24小时
        {
            stats  = drainRmstSzService.statisticsRmstSzFactry();
        }

        //构建ECharts所需数据结构
        Map<String, Object> chartData = new LinkedHashMap<>();

        // X轴数据（时间年份）
        List<String> timeDataValue = new ArrayList<>(stats.keySet());
        chartData.put("timeDataValue", timeDataValue);

        //出水量
        List<Double> estimatedSales = stats.values().stream()
                .map(arr -> arr[0])
                .collect(Collectors.toList());
        //转成 万吨 单位
        List<BigDecimal>  estimatedSalesBd =  convertToUnit(
                estimatedSales,
                BigDecimal.valueOf(10000), // 万元转换
                2                         // 保留2位小数
        );

        // 厂设计规模
        List<Double> actualSales = stats.values().stream()
                .map(arr -> arr[1])
                .collect(Collectors.toList());
        //转成 万吨 单位
        List<BigDecimal>  actualSalesBd =  convertToUnit(
                actualSales,
                BigDecimal.valueOf(10000), // 万元转换
                2                         // 保留2位小数
        );

        // 系列数据(出水量、设计规模)
        List<Map<String, Object>> series = Arrays.asList(
                Map.of(
                        "name", "污水处理量",
                        "type", "bar",
                        "data", estimatedSalesBd
                ),
                Map.of(
                        "name", "设计规模",
                        "type", "line",
                        "data", actualSalesBd
                )
        );

        chartData.put("series", series);

        return chartData;
    }

    public static List<BigDecimal> convertToUnit(List<Double> values,
                                                 BigDecimal divisor,
                                                 int finalScale) {
        return values.stream()
                .map(value -> value != null ? value : 0.0)
                .map(BigDecimal::valueOf)
                .map(bd -> bd.divide(divisor, finalScale + 2, RoundingMode.HALF_UP))
                .map(bd -> bd.setScale(finalScale, RoundingMode.HALF_UP))
                .collect(Collectors.toList());
    }




    /**
     * 转成“万吨”单位
     * @param toDayOut
     * @return
     */
    private String ConvertWTons(BigDecimal toDayOut)
    {

        String wTons  = "";
        if(toDayOut!=null)
        {

            wTons = toDayOut.divide(BigDecimal.valueOf(10000), 4, RoundingMode.HALF_UP)
                    .stripTrailingZeros()  // 去除末尾多余的零
                    .toPlainString();
        }

        return wTons;

    }

    // 过滤当天的数据
    private  List<DrainRmstYwDayVo> filterToday(List<DrainRmstYwDayVo> list) {
        LocalDateTime start = DateTimeFilterUtils.getStartOfToday();
        LocalDateTime end = DateTimeFilterUtils.getEndOfToday();

        return list.stream()
                .filter(vo -> vo.getCjTime() != null)
                .filter(vo -> !vo.getCjTime().isBefore(start) && !vo.getCjTime().isAfter(end))
                .collect(Collectors.toList());
    }

    // 过滤昨天的数据
    private  List<DrainRmstYwDayVo> filterYesterday(List<DrainRmstYwDayVo> list) {
        LocalDateTime start = DateTimeFilterUtils.getStartOfYesterday();
        LocalDateTime end = DateTimeFilterUtils.getEndOfYesterday();

        return list.stream()
                .filter(vo -> vo.getCjTime() != null)
                .filter(vo -> !vo.getCjTime().isBefore(start) && !vo.getCjTime().isAfter(end))
                .collect(Collectors.toList());
    }

    // 过滤当月的数据
    private   List<DrainRmstYwDayVo> filterThisMonth(List<DrainRmstYwDayVo> list) {
        LocalDateTime start = DateTimeFilterUtils.getStartOfMonth();
        LocalDateTime end = DateTimeFilterUtils.getEndOfMonth();

        return list.stream()
                .filter(vo -> vo.getCjTime() != null)
                .filter(vo -> !vo.getCjTime().isBefore(start) && !vo.getCjTime().isAfter(end))
                .collect(Collectors.toList());
    }

    // 过滤当年的数据
    private   List<DrainRmstYwDayVo> filterThisYear(List<DrainRmstYwDayVo> list) {
        LocalDateTime start = DateTimeFilterUtils.getStartOfYear();
        LocalDateTime end = DateTimeFilterUtils.getEndOfYear();

        return list.stream()
                .filter(vo -> vo.getCjTime() != null)
                .filter(vo -> !vo.getCjTime().isBefore(start) && !vo.getCjTime().isAfter(end))
                .collect(Collectors.toList());
    }

    /**
     * 移动端查询污水处理厂的处理量列表
     * @param request
     * @return
     */
    @Override
    public PageDataInfo<DrainRmstYwDayVo> getAppFactoryRmstYwDay(DrainRmstYwDayVoReq request)
    {
        LambdaQueryWrapper<DrainRmstYwDayVo> wrapper = new LambdaQueryWrapper<>();
        //污水厂代码
        wrapper.eq(StringUtils.isNotBlank(request.getFactId()),DrainRmstYwDayVo::getFactId,request.getFactId());
        // 采集时间
        if(request.getCjTimeStrart()!=null && request.getEndTime()!=null)
        {
            wrapper.ge(DrainRmstYwDayVo::getCjTime, request.getCjTimeStrart().toLocalDate().atStartOfDay())  // 7天前
                    .le(DrainRmstYwDayVo::getCjTime,request.getEndTime().toLocalDate()
                            .atTime(23, 59, 59));
        }
        wrapper.orderByDesc(DrainRmstYwDayVo::getCjTime);

        Page<DrainRmstYwDayVo> page = drainRmstYwDayVoMapper.selectPage(request.getPageQuery().build(), wrapper);

        return PageDataInfo.build(page);
    }
}
